package org.framework.common.api.support.model;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.framework.common.api.support.annotation.Chosen;
import org.framework.common.api.support.annotation.ChosenType;
import org.springframework.util.ReflectionUtils;

/**
 * 下拉结构数据模型
 * <p>描述: </p>
 * <p>Company: Professional</p>
 * @author chanlong(陈龙)
 * @date 2016年1月30日 下午1:20:26
 * @version 1.0.2016
 */
public class ChosenModel implements Serializable {

	/** serialVersionUID(long):. */
	private static final long serialVersionUID = 5286679072091702760L;

	private String text;
	
	private String value;
	
	private Map<String, Object> attributes;
	
	public static ChosenModel[] create(final List<?> result){
		List<ChosenModel> chosens = new ArrayList<ChosenModel>();
		for (Object bean : result) {
			Class<?> clazz = bean.getClass();
			ChosenModel chosen = new ChosenModel();
			ReflectionUtils.doWithMethods(clazz, chosen.new MethodCallback(chosen, bean));
			chosens.add(chosen);
		}
		return chosens.toArray(new ChosenModel[result.size()]);
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public Map<String, Object> getAttributes() {
		return attributes;
	}

	public void setAttributes(Map<String, Object> attributes) {
		this.attributes = attributes;
	}
	
	public void addAttribute(final String name, final Object value){
		if(attributes == null){
			attributes = new HashMap<String, Object>();
		}
		attributes.put(name, value);
	}
	
	/*
	 * 方法回调函数
	 */
	private class MethodCallback implements org.springframework.util.ReflectionUtils.MethodCallback{
		
		private Object bean;
		private ChosenModel model;
		
		private MethodCallback(ChosenModel model, Object bean) {
			this.bean = bean;
			this.model = model;
		}
		
		@Override
		public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
			Chosen chosen = method.getAnnotation(Chosen.class);
			try {
				if(chosen != null){
					ChosenType[] types = chosen.type();
					for (ChosenType type : types) {
						switch (type) {
							case TEXT:
								Object text = ReflectionUtils.invokeMethod(method, bean);
								model.setText(String.valueOf(text));
							break;
							case VALUE:
								Object value = ReflectionUtils.invokeMethod(method, bean);
								model.setValue(String.valueOf(value));
							break;
							case ATTRIBUTE:
								String name = method.getName().replace("get", "").toLowerCase();
								Object attribute = ReflectionUtils.invokeMethod(method, bean);
								model.addAttribute(name, attribute);
							break;
							default:
								model.setText(String.valueOf(method.invoke(bean)));
								model.setValue(String.valueOf(method.invoke(bean)));
							break;
						}
					}
				}
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
	}
	
}
